package com.ruoyi.fun.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.fun.domain.EcProductSku;
import com.ruoyi.fun.domain.EcStockLog;
import com.ruoyi.fun.mapper.EcProductSkuMapper;
import com.ruoyi.fun.service.IEcStockLogService;
import com.ruoyi.fun.service.IEcStockService;

/**
 * 库存管理Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-01-15
 */
@Service
public class EcStockServiceImpl implements IEcStockService 
{
    private static final Logger logger = LoggerFactory.getLogger(EcStockServiceImpl.class);
    
    // 操作类型常量定义
    private static final String OPERATION_TYPE_IN = "1";      // 入库
    private static final String OPERATION_TYPE_OUT = "2";     // 出库  
    private static final String OPERATION_TYPE_ADJUST = "3";  // 调整
    
    @Autowired
    private EcProductSkuMapper ecProductSkuMapper;
    
    @Autowired
    private IEcStockLogService ecStockLogService;

    /**
     * 检查商品SKU库存是否充足
     */
    @Override
    public boolean checkStock(Long skuId, Long quantity) {
        if (skuId == null || quantity == null || quantity <= 0) {
            logger.warn("库存检查参数无效: skuId={}, quantity={}", skuId, quantity);
            return false;
        }
        
        try {
            EcProductSku sku = ecProductSkuMapper.selectEcProductSkuBySkuId(skuId);
            if (sku == null) {
                logger.warn("SKU不存在: skuId={}", skuId);
                return false;
            }
            
            Long currentStock = sku.getStock();
            if (currentStock == null) {
                currentStock = 0L;
            }
            
            boolean hasEnoughStock = currentStock >= quantity;
            logger.info("库存检查结果: skuId={}, 当前库存={}, 需要数量={}, 结果={}", 
                       skuId, currentStock, quantity, hasEnoughStock);
            
            return hasEnoughStock;
        } catch (Exception e) {
            logger.error("库存检查异常: skuId={}, quantity={}", skuId, quantity, e);
            return false;
        }
    }
    
    /**
     * 批量检查商品SKU库存
     */
    @Override
    public Map<Long, Boolean> batchCheckStock(List<Map<String, Object>> stockCheckList) {
        Map<Long, Boolean> result = new HashMap<>();
        
        if (stockCheckList == null || stockCheckList.isEmpty()) {
            logger.warn("批量库存检查参数为空");
            return result;
        }
        
        for (Map<String, Object> item : stockCheckList) {
            try {
                Long skuId = Long.valueOf(item.get("skuId").toString());
                Long quantity = Long.valueOf(item.get("quantity").toString());
                
                boolean hasStock = checkStock(skuId, quantity);
                result.put(skuId, hasStock);
            } catch (Exception e) {
                logger.error("批量库存检查单项异常: item={}", item, e);
                // 异常情况下认为库存不足
                if (item.get("skuId") != null) {
                    try {
                        Long skuId = Long.valueOf(item.get("skuId").toString());
                        result.put(skuId, false);
                    } catch (Exception ex) {
                        logger.error("解析skuId异常: item={}", item, ex);
                    }
                }
            }
        }
        
        return result;
    }
    
    /**
     * 扣减商品SKU库存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deductStock(Long skuId, Long quantity, String orderNo) {
        if (skuId == null || quantity == null || quantity <= 0) {
            logger.warn("库存扣减参数无效: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
            return false;
        }
        
        try {
            // 先检查库存是否充足
            if (!checkStock(skuId, quantity)) {
                logger.warn("库存不足，无法扣减: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
                return false;
            }
            
            // 获取当前SKU信息
            EcProductSku sku = ecProductSkuMapper.selectEcProductSkuBySkuId(skuId);
            if (sku == null) {
                logger.warn("SKU不存在，无法扣减库存: skuId={}", skuId);
                return false;
            }
            
            Long originalStock = sku.getStock() != null ? sku.getStock() : 0L;
            Long newStock = originalStock - quantity;
            
            // 更新库存 - 只更新库存字段，避免覆盖销量
            EcProductSku updateSku = new EcProductSku();
            updateSku.setSkuId(skuId);
            updateSku.setStock(newStock);
            int updateResult = ecProductSkuMapper.updateEcProductSku(updateSku);
            
            if (updateResult > 0) {
                // 记录库存变动日志
                recordStockLog(skuId, OPERATION_TYPE_OUT, quantity, originalStock, newStock, orderNo, "订单支付扣减库存");
                
                logger.info("库存扣减成功: skuId={}, 原库存={}, 扣减数量={}, 新库存={}, 订单号={}", 
                           skuId, originalStock, quantity, newStock, orderNo);
                return true;
            } else {
                logger.warn("库存扣减失败，数据库更新失败: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
                return false;
            }
        } catch (Exception e) {
            logger.error("库存扣减异常: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo, e);
            throw e; // 抛出异常以触发事务回滚
        }
    }
    
    /**
     * 批量扣减商品SKU库存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchDeductStock(List<Map<String, Object>> stockDeductList, String orderNo) {
        if (stockDeductList == null || stockDeductList.isEmpty()) {
            logger.warn("批量库存扣减参数为空: orderNo={}", orderNo);
            return false;
        }
        
        try {
            // 先批量检查库存
            Map<Long, Boolean> stockCheckResult = batchCheckStock(stockDeductList);
            
            // 检查是否所有商品都有足够库存
            for (Map.Entry<Long, Boolean> entry : stockCheckResult.entrySet()) {
                if (!entry.getValue()) {
                    logger.warn("批量库存扣减失败，SKU库存不足: skuId={}, orderNo={}", entry.getKey(), orderNo);
                    return false;
                }
            }
            
            // 逐个扣减库存
            for (Map<String, Object> item : stockDeductList) {
                Long skuId = Long.valueOf(item.get("skuId").toString());
                Long quantity = Long.valueOf(item.get("quantity").toString());
                
                if (!deductStock(skuId, quantity, orderNo)) {
                    logger.error("批量库存扣减失败: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
                    throw new RuntimeException("库存扣减失败: skuId=" + skuId);
                }
            }
            
            logger.info("批量库存扣减成功: 共{}个SKU, orderNo={}", stockDeductList.size(), orderNo);
            return true;
        } catch (Exception e) {
            logger.error("批量库存扣减异常: orderNo={}", orderNo, e);
            throw e; // 抛出异常以触发事务回滚
        }
    }
    
    /**
     * 恢复商品SKU库存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean restoreStock(Long skuId, Long quantity, String orderNo) {
        if (skuId == null || quantity == null || quantity <= 0) {
            logger.warn("库存恢复参数无效: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
            return false;
        }
        
        try {
            EcProductSku sku = ecProductSkuMapper.selectEcProductSkuBySkuId(skuId);
            if (sku == null) {
                logger.warn("SKU不存在，无法恢复库存: skuId={}", skuId);
                return false;
            }
            
            Long originalStock = sku.getStock() != null ? sku.getStock() : 0L;
            Long newStock = originalStock + quantity;
            
            // 更新库存 - 只更新库存字段，避免覆盖销量
            EcProductSku updateSku = new EcProductSku();
            updateSku.setSkuId(skuId);
            updateSku.setStock(newStock);
            int updateResult = ecProductSkuMapper.updateEcProductSku(updateSku);
            
            if (updateResult > 0) {
                // 记录库存变动日志
                recordStockLog(skuId, OPERATION_TYPE_IN, quantity, originalStock, newStock, orderNo, "订单取消恢复库存");
                
                logger.info("库存恢复成功: skuId={}, 原库存={}, 恢复数量={}, 新库存={}, 订单号={}", 
                           skuId, originalStock, quantity, newStock, orderNo);
                return true;
            } else {
                logger.warn("库存恢复失败，数据库更新失败: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo);
                return false;
            }
        } catch (Exception e) {
            logger.error("库存恢复异常: skuId={}, quantity={}, orderNo={}", skuId, quantity, orderNo, e);
            throw e; // 抛出异常以触发事务回滚
        }
    }
    
    /**
     * 获取商品SKU当前库存数量
     */
    @Override
    public Long getCurrentStock(Long skuId) {
        if (skuId == null) {
            logger.warn("获取库存参数无效: skuId={}", skuId);
            return 0L;
        }
        
        try {
            EcProductSku sku = ecProductSkuMapper.selectEcProductSkuBySkuId(skuId);
            if (sku == null) {
                logger.warn("SKU不存在: skuId={}", skuId);
                return 0L;
            }
            
            return sku.getStock() != null ? sku.getStock() : 0L;
        } catch (Exception e) {
            logger.error("获取库存异常: skuId={}", skuId, e);
            return 0L;
        }
    }
    
    /**
     * 记录库存变动日志
     */
    private void recordStockLog(Long skuId, String operationType, Long quantity, 
                               Long beforeStock, Long afterStock, String orderNo, String remark) {
        try {
            EcStockLog stockLog = new EcStockLog();
            stockLog.setSkuId(skuId);
            stockLog.setOperationType(operationType);
            stockLog.setOperationQuantity(quantity);
            stockLog.setBeforeStock(beforeStock);
            stockLog.setAfterStock(afterStock);
            stockLog.setOrderNo(orderNo);
            stockLog.setOperationReason(remark);
            stockLog.setCreateTime(new Date());
            
            ecStockLogService.insertEcStockLog(stockLog);
            logger.debug("库存变动日志记录成功: skuId={}, operationType={}, quantity={}", 
                        skuId, operationType, quantity);
        } catch (Exception e) {
            logger.error("记录库存变动日志失败: skuId={}, operationType={}, quantity={}", 
                        skuId, operationType, quantity, e);
            // 日志记录失败不影响主流程
        }
    }
}